﻿using System;
using System.Collections.Generic;
using System.Text;
using __Able.Network.Utils;

namespace __Able.Network.Packets
{
    /// <summary>
    /// 基本协议族的输出包基类
    /// 基本协议族的包都具有以下的格式:
    /// 1. 包头标志，1字节，0x02
    /// 2. 客户端版本代码，2字节
    /// 3. 命令，2字节
    /// 4. 包序号, 2字节
    /// 5. 用户QQ号，4字节
    /// 6. 包体
    /// 7. 包尾标志，1字节，0x03
    /// Note: 6部分将用会话密钥加密, 登录包例外，6部分要用密码密钥加密。请求登录令牌包例外，6部分不需加密
    /// </summary>
    public abstract class _BasicOutPacket : _OutPacket
    {
        /// <summary>
        /// 基本协议族
        /// </summary>
        public const uint PROTOCOL_FAMILY_BASIC = 0x1;
        /// <summary>
        /// 基本协议族包头
        /// </summary>
        public const byte HEADER_BASIC_FAMILY = 0x02;
        /// <summary>
        /// 基本协议族包尾
        /// </summary>
        public const byte TAIL_BASIC_FAMILY = 0x03;
        /// <summary>
        /// 基本协议族输出包的包头长度
        /// </summary>
        public const int LENGTH_BASIC_FAMILY_OUT_HEADER = 11;
        /// <summary>
        /// 基本协议族包尾长度
        /// </summary>
        public const int LENGTH_BASIC_FAMILY_TAIL = 1;
        /// <summary>
        /// 
        /// </summary>
        private uint userId;

        /// <summary>
        /// 构造一个参数指定的包.
        /// </summary>
        /// <param name="command">命令.</param>
        /// <param name="ack">是否需要回应.</param>
        /// <param name="user">The user.</param>
        protected _BasicOutPacket(ushort command, bool ack, User user) : base(HEADER_BASIC_FAMILY, command, ack, user) { }
        /// <summary>
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="user">The user.</param>
        protected _BasicOutPacket(ByteBuffer buf, User user) : base(buf, buf.Length - buf.Position, user) { }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="length"></param>
        /// <param name="user"></param>
        protected _BasicOutPacket(ByteBuffer buf, int length, User user) : base(buf, length, user) { }
        /// <summary>
        /// 校验头部
        /// </summary>
        /// <returns></returns>
        protected override bool ValidateHeader()
        {
            return userId == user.ID;
        }
        /// <summary>
        /// 得到包体的字节数组
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="length">包总长度</param>
        /// <returns>包体字节数组</returns>
        protected override byte[] GetBodyBytes(ByteBuffer buf, int length)
        {
            // 得到包体长度
            int bodyLen = length - LENGTH_BASIC_FAMILY_OUT_HEADER - LENGTH_BASIC_FAMILY_TAIL;
            if (!user.IsUdp) bodyLen -= 2;
            // 得到加密的包体内容
            byte[] body = buf.GetByteArray(bodyLen);
            return body;
        }
        /// <summary>
        /// 得到UDP形式包的总长度，不考虑TCP形式
        /// </summary>
        /// <param name="bodyLength">包体长度.</param>
        /// <returns>包长度</returns>
        protected override int GetLength(int bodyLength)
        {
            return LENGTH_BASIC_FAMILY_OUT_HEADER + LENGTH_BASIC_FAMILY_TAIL + bodyLength + (user.IsUdp ? 0 : 2);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        protected override void ParseTail(ByteBuffer buf)
        {
            buf.Get();
        }
        /// <summary>
        /// 
        /// </summary>
        public override string PacketName
        {
            get { return "Unknown Outcoming Packet - Basic Family"; }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        protected override void PutHead(ByteBuffer buf)
        {
            if (!user.IsUdp) buf.PutUShort(0);
            buf.Put(Header);
            buf.PutUShort(Source);
            buf.PutUShort(Command);
            buf.PutUShort(Sequence);
            buf.PutInt(user.ID);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="startPos"></param>
        protected override void PostFill(ByteBuffer buf, int startPos)
        {
            // 如果是tcp包，到包的开头处填上包长度，然后回到目前的pos
            if (!user.IsUdp)
            {
                int len = buf.Length - startPos;
                buf.PutUShort(startPos, (ushort)len);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        protected override void PutTail(ByteBuffer buf)
        {
            buf.Put(TAIL_BASIC_FAMILY);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="buf"></param>
        protected override void ParseHeader(ByteBuffer buf)
        {
            if (!user.IsUdp) buf.GetChar();
            Header = buf.Get();
            Source = buf.GetUShort();
            Command = buf.GetUShort();
            Sequence = buf.GetUShort();
            userId = buf.GetUInt();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override int GetHeaderLength()
        {
            return LENGTH_BASIC_FAMILY_OUT_HEADER + (user.IsUdp ? 0 : 2);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override int GetTailLength()
        {
            return LENGTH_BASIC_FAMILY_TAIL;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "PacketName: " + PacketName + " Sequence: " + (int)Sequence + " Time: " + DateTime.ToString();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="body"></param>
        /// <returns></returns>
        public override byte[] GetDecryptKey(byte[] body)
        {
            return user.SessionKey;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="body"></param>
        /// <returns></returns>
        public override byte[] GetFallbackDecryptKey(byte[] body)
        {
            return user.PasswordKey;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="body"></param>
        /// <returns></returns>
        public override byte[] GetEncryptKey(byte[] body)
        {
            return user.SessionKey;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override uint GetFamily()
        {
            return PROTOCOL_FAMILY_BASIC;
        }
    }
}
